"""
功能：将截图，批量插入到word文档《性能测试报告》中
输入：.png截图文件夹路径，.docx报告路径，图片重命名替换字符串字典
输出：插入图片的报告
报告要求：需建立与图片对应的，场景、并发与性能指标的标题

    1、rename_files：处理截图名称，通过字典replacement_dict替换，重命名图片名称。
                    正确命名：场景描述-并发数-性能指标.png，例如：单位职工参保登记-300-测试结果摘要.png
    2、get_image_info：获取图片信息，包括场景描述、并发数、性能指标
    3、insert_image：根据图片信息，判断插入位置，插入图片到文档
    4、add_images_to_report：插入所有图片，报告保存。
    5、get_image_keys：预处理图片路径信息，列表转换路径字典：{场景描述：{并发数：{性能指标：路径}}}
    6、insert_image_two：向已打开word，插入图片。优化版：通过预处理图片字典，遍历一次word段落，对比每个图片关键信息。减少了word遍历次数
"""

# !/usr/bin/env python
# -*- coding:utf-8 -*-
import os
import re
from datetime import datetime
from docx import Document
from docx.shared import Inches

folder_path = r'C:\Users\11970\Downloads\Report diagram'  # 图片文件夹路径
report_path = r'C:\Users\11970\Downloads\Report diagram\性能测试报告.docx'  # 报告路径

# 旧字符串及其替换的新字符串
replacement_dict = {'正式-': '',
                    '-10-606.csv': '',
                    'jp@gc - Response Times Over Time': '事务响应时间',
                    'jp@gc - Transactions per Second': '每秒请求通过数（TPS）',
                    '聚合报告': '测试结果摘要',
                    'jp@gc - Hits per Second': '每秒点击数',
                    '-50-': '-50并发-',
                    '-100-': '-100并发-',
                    '-200-': '-200并发-',
                    '-300-': '-300并发-',
                    '-400-': '-400并发-',
                    '-500-': '-500并发-',
                    '-1000-': '-1000并发-',
                    }


def rename_files(folder_path, replacement_dict):
    """
    重命名文件夹内的所有png文件
    :param folder_path: 图片文件夹路径
    :param replacement_dict: 替换字符串字典
    :return: 重命名后图片路径列表
    """
    image_paths = []  # 存储图片路径的列表
    # 遍历文件夹内的所有文件
    try:
        for filename in os.listdir(folder_path):
            if filename.endswith('.png'):  # 检查文件是否为.png
                new_name = filename
                for key, value in replacement_dict.items():
                    if key in filename:
                        new_name = new_name.replace(key, value)  # 替换字符串
                if new_name != filename:  # 如果文件名发生了变化
                    os.rename(os.path.join(folder_path, filename), os.path.join(folder_path, new_name))
                    # print(f'"{filename}" to "{new_name}"')

                image_paths.append(os.path.join(folder_path, new_name))
    except Exception as e:
        print(f"重命名过程中发生错误: {e}")
    return image_paths


def get_image_info(image_path):
    """
    获取图片信息
    :param image_path: 图片路径
    :return: 图片信息：场景描述、并发数、性能指标
    """
    filename = os.path.basename(image_path)  # 提取文件名
    pattern = r'(.*)-(.*)-(.*)\.png'  # 定义正则表达式模式
    match = re.match(pattern, filename)  # 匹配文件名

    if match:
        scene_description = match.group(1)  # 场景描述
        concurrency = match.group(2)  # 并发数
        metric = match.group(3)  # 性能指标
        return scene_description, concurrency, metric
    else:
        print(f"{image_path}文件名格式不正确，无法解析。")
        return None, None, None


def insert_image(image_paths, doc, count):
    """
    遍历图片路径列表，根据图片信息，判断插入位置，插入图片到文档
    :param image_paths: 图片路径
    :param doc: 打开的word文档
    :param count: 成功图片数
    :return count: 成功图片数
    """
    for image_path in image_paths:
        scene_description, concurrency, metric = get_image_info(image_path)
        scene_description_flag = False  # 关键词标记,辅助定位图片插入位置
        concurrency_flag = False
        # 遍历文档中的所有段落
        for paragraph in doc.paragraphs[100:]:  # 切片，去除目录等
            # p = paragraph.text
            if scene_description in paragraph.text:
                scene_description_flag = True
            elif scene_description_flag and concurrency in paragraph.text:
                concurrency_flag = True
            elif concurrency_flag and metric in paragraph.text:
                run = paragraph.add_run()  # 创建一个新的Run对象并添加到当前段落
                run.add_break()  # 添加一个换行符
                run.add_picture(image_path, width=Inches(5.5))  # 在当前Run中插入图, 设置宽高, height=Inches(3.0)3.0英寸
                # print(f"{image_path}插入成功")
                count += 1
                scene_description_flag = False  # 关键词标记,辅助定位图片插入位置
                concurrency_flag = False
    return count


def add_images_to_report(folder_path, report_path, replacement_dict):
    """
    插入所有图片，报告保存。
    :param folder_path: 文件夹路径
    :param report_path: 报告路径
    :param replacement_dict: 替换字符串字典
    :return: None
    """
    count = 0
    start_time = datetime.now()
    image_paths = rename_files(folder_path, replacement_dict)
    try:
        doc = Document(report_path)  # 打开Word文档
        # count = insert_image(image_paths, doc, count)  # 插入图片
        count = insert_image_two(image_paths, doc, count)  # 插入图片，优化版
        if count > 0:
            doc.save(report_path)  # 保存修改后的文档
    except Exception as e:
        print(f"修改文档时发生错误：{e}")
    finally:
        completion_rate = (count / len(image_paths)) * 100 if len(image_paths) > 0 else 0  # 计算完成度
        end_time = datetime.now()
        time_duration = (end_time - start_time).total_seconds()
        print(
            f"文件夹图片【{len(image_paths)}】张，实际插入【{count}】张\n完成度：{completion_rate:.2f}%\n耗时：{time_duration}秒")


def get_image_keys(image_paths):
    """
    预处理图片路径信息，列表转换字典
    :param image_paths: 图片路径列表
    :return: 路径字典：{场景描述：{并发数：{性能指标：路径}}}
    """
    image_keys = {}
    for image_path in image_paths:
        scene_description, concurrency, metric = get_image_info(image_path)
        # 检查是否需要创建新的字典层级
        if scene_description not in image_keys:
            image_keys[scene_description] = {}
        if concurrency not in image_keys[scene_description]:
            image_keys[scene_description][concurrency] = {}
        image_keys[scene_description][concurrency][metric] = image_path         # 保存文件路径到对应的位置
    return image_keys


def insert_image_two(image_paths, doc, count):
    """
    向已打开word，插入图片。优化版：通过预处理图片字典，遍历一次word段落，对比每个图片关键信息。减少了word遍历次数
    :param image_paths: 图片路径
    :param doc: 打开的word文档
    :param count: 成功图片数
    :return count: 成功图片数
    """
    image_keys = get_image_keys(image_paths)
    scene_description_flag = False  # 关键词标记,辅助定位图片插入位置
    concurrency_flag = False

    for paragraph in doc.paragraphs[100:]:  # 切片，去除目录等。遍历word's段落
        if not scene_description_flag:          # 场景描述
            for scene_description in image_keys.keys():
                if scene_description in paragraph.text:
                    scene_description_flag = True
                    break
        elif scene_description_flag and not concurrency_flag:   # 并发数
            for concurrency in image_keys[scene_description].keys():
                if concurrency in paragraph.text:
                    concurrency_flag = True
                    break
        elif concurrency_flag:                                  # 性能指标
            for metric in image_keys[scene_description][concurrency].keys():
                if metric in paragraph.text:
                    run = paragraph.add_run()  # 创建一个新的Run对象并添加到当前段落
                    run.add_break()  # 添加一个换行符
                    run.add_picture(image_keys[scene_description][concurrency][metric], width=Inches(5.5))  # 在当前
                    count += 1

                    del image_keys[scene_description][concurrency][metric]  # 删除已插入图片字典
                    if not image_keys[scene_description][concurrency]:
                        del image_keys[scene_description][concurrency]
                        concurrency_flag = False
                    if not image_keys[scene_description]:
                        del image_keys[scene_description]
                        scene_description_flag = False  # 关键词标记,辅助定位图片插入位置
                    break
    if count > 0 and image_keys:    # 输出未插入图片信息
        print("以下图片未插入：")
        for scene_description in image_keys.keys():
            for concurrency in image_keys[scene_description].keys():
                for metric in image_keys[scene_description][concurrency].keys():
                    print(f"\t{scene_description} {concurrency} {metric}")
    return count



if __name__ == '__main__':
    print("开始插入图片...")
    add_images_to_report(folder_path, report_path, replacement_dict)
